/**
 * 平台账号服务
 * 处理平台账号相关的业务逻辑
 */

const db = require('../middleware/dbProxy');
const scheduleManager = require('../middleware/schedule/index.js');
const locationService = require('./locationService');

class PlaAccountService {
    /**
     * 根据ID获取账号信息
     * @param {number} id - 账号ID
     * @returns {Promise<Object>} 账号信息
     */
    async getAccountById(id) {
        const pla_account = db.getModel('pla_account');
        const device_status = db.getModel('device_status');

        const account = await pla_account.findByPk(id);
        if (!account) {
            throw new Error('账号不存在');
        }

        const accountData = account.get({ plain: true });

        // 从 device_status 查询在线状态和登录状态
        const deviceStatus = await device_status.findByPk(account.sn_code);
        if (deviceStatus) {
            accountData.is_online = deviceStatus.isOnline || false;
            accountData.is_logged_in = deviceStatus.isLoggedIn || false;
        } else {
            accountData.is_online = false;
            accountData.is_logged_in = false;
        }

        return accountData;
    }

    /**
     * 获取账号列表
     * @param {Object} params - 查询参数
     * @returns {Promise<Object>} 账号列表
     */
    async getAccountList(params) {
        const pla_account = db.getModel('pla_account');
        const device_status = db.getModel('device_status');
        const op = db.getModel('op');

        const { key, value, platform_type, is_online, limit, offset } = params;

        const where = { is_delete: 0 };

        // 搜索条件
        if (key && value) {
            where[key] = { [op.like]: `%${value}%` };
        }

        // 平台筛选
        if (platform_type) {
            where.platform_type = platform_type;
        }

        // 如果按在线状态筛选，需要先查询在线设备的 sn_code
        let onlineSnCodes = null;
        if (is_online !== undefined && is_online !== null) {
            const onlineDevices = await device_status.findAll({
                where: { isOnline: is_online },
                attributes: ['sn_code']
            });
            onlineSnCodes = onlineDevices.map(device => device.sn_code);

            // 如果筛选在线但没有任何在线设备，直接返回空结果
            if (is_online && onlineSnCodes.length === 0) {
                return {
                    count: 0,
                    rows: []
                };
            }

            // 如果筛选离线，需要在 where 中排除在线设备的 sn_code
            if (!is_online && onlineSnCodes.length > 0) {
                where.sn_code = { [op.notIn]: onlineSnCodes };
            }
        }

        const result = await pla_account.findAndCountAll({
            where,
            limit,
            offset,
            order: [['id', 'DESC']]
        });

        // 批量查询所有账号对应的设备状态
        const snCodes = result.rows.map(account => account.sn_code);
        const deviceStatuses = await device_status.findAll({
            where: { sn_code: { [op.in]: snCodes } },
            attributes: ['sn_code', 'isOnline']
        });

        // 创建 sn_code 到 isOnline 的映射
        const statusMap = {};
        deviceStatuses.forEach(status => {
            statusMap[status.sn_code] = status.isOnline;
        });

        // 处理返回数据，添加 is_online 字段
        const rows = result.rows.map(account => {
            const accountData = account.get({ plain: true });
            accountData.is_online = statusMap[account.sn_code] || false;
            return accountData;
        });

        return {
            count: result.count,
            rows
        };
    }

    /**
     * 创建账号
     * @param {Object} data - 账号数据
     * @returns {Promise<Object>} 创建的账号
     */
    async createAccount(data) {
        const pla_account = db.getModel('pla_account');

        const { name, sn_code, platform_type, login_name, pwd, keyword, ...otherData } = data;

        if (!name || !sn_code || !platform_type || !login_name) {
            throw new Error('账户名、设备SN码、平台和登录名为必填项');
        }

        // 将布尔字段从 true/false 转换为 0/1
        const booleanFields = ['auto_deliver', 'auto_chat', 'auto_reply', 'auto_active'];
        const processedData = {
            name,
            sn_code,
            platform_type,
            login_name,
            pwd: pwd || '',
            keyword: keyword || '',
            ...otherData
        };
        
        booleanFields.forEach(field => {
            if (processedData[field] !== undefined && processedData[field] !== null) {
                processedData[field] = processedData[field] ? 1 : 0;
            }
        });

        const account = await pla_account.create(processedData);

        return account;
    }

    /**
     * 更新账号信息
     * @param {number} id - 账号ID
     * @param {Object} updateData - 更新的数据
     * @returns {Promise<void>}
     */
    async updateAccount(id, updateData) {
        const pla_account = db.getModel('pla_account');

        if (!id) {
            throw new Error('账号ID不能为空');
        }

        const account = await pla_account.findByPk(id);
        if (!account) {
            throw new Error('账号不存在');
        }

        // 将布尔字段从 true/false 转换为 0/1，确保数据库兼容性
        const booleanFields = ['auto_deliver', 'auto_chat', 'auto_reply', 'auto_active'];
        const processedData = { ...updateData };
        booleanFields.forEach(field => {
            if (processedData[field] !== undefined && processedData[field] !== null) {
                processedData[field] = processedData[field] ? 1 : 0;
            }
        });

        await pla_account.update(processedData, { where: { id } });
    }

    /**
     * 删除账号（软删除）
     * @param {number} id - 账号ID
     * @returns {Promise<void>}
     */
    async deleteAccount(id) {
        const pla_account = db.getModel('pla_account');

        if (!id) {
            throw new Error('账号ID不能为空');
        }

        // 软删除
        const result = await pla_account.update(
            { is_delete: 1 },
            { where: { id } }
        );

        if (result[0] === 0) {
            throw new Error('账号不存在');
        }
    }

    /**
     * 获取账号的任务列表
     * @param {Object} params - 查询参数
     * @returns {Promise<Object>} 任务列表
     */
    async getAccountTasks(params) {
        const pla_account = db.getModel('pla_account');
        const task_status = db.getModel('task_status');

        const { id, limit, offset } = params;

        if (!id) {
            throw new Error('账号ID不能为空');
        }

        // 先获取账号信息
        const account = await pla_account.findByPk(id);
        if (!account) {
            throw new Error('账号不存在');
        }

        // 通过 sn_code 查询任务列表
        const result = await task_status.findAndCountAll({
            where: {
                sn_code: account.sn_code
            },
            limit,
            offset,
            order: [['id', 'DESC']]
        });

        return {
            count: result.count,
            rows: result.rows
        };
    }

    /**
     * 获取账号的指令列表
     * @param {Object} params - 查询参数
     * @returns {Promise<Object>} 指令列表
     */
    async getAccountCommands(params) {
        const pla_account = db.getModel('pla_account');
        const task_commands = db.getModel('task_commands');
        const Sequelize = require('sequelize');

        const { id, limit, offset } = params;

        if (!id) {
            throw new Error('账号ID不能为空');
        }

        // 先获取账号信息
        const account = await pla_account.findByPk(id);
        if (!account) {
            throw new Error('账号不存在');
        }

        // 获取 sequelize 实例
        const sequelize = task_commands.sequelize;

        // 使用原生 SQL JOIN 查询
        const countSql = `
          SELECT COUNT(DISTINCT tc.id) as count
          FROM task_commands tc
          INNER JOIN task_status ts ON tc.task_id = ts.id
          WHERE ts.sn_code = :sn_code
        `;

        const dataSql = `
          SELECT tc.*
          FROM task_commands tc
          INNER JOIN task_status ts ON tc.task_id = ts.id
          WHERE ts.sn_code = :sn_code
          ORDER BY tc.id DESC
          LIMIT :limit OFFSET :offset
        `;

        // 并行执行查询和计数
        const [countResult, dataResult] = await Promise.all([
            sequelize.query(countSql, {
                replacements: { sn_code: account.sn_code },
                type: Sequelize.QueryTypes.SELECT
            }),
            sequelize.query(dataSql, {
                replacements: {
                    sn_code: account.sn_code,
                    limit: limit,
                    offset: offset
                },
                type: Sequelize.QueryTypes.SELECT
            })
        ]);

        const count = countResult[0]?.count || 0;

        // 将原始数据转换为 Sequelize 模型实例
        const rows = dataResult.map(row => {
            return task_commands.build(row, { isNewRecord: false });
        });

        return {
            count: parseInt(count),
            rows: rows
        };
    }

    /**
     * 执行账号指令
     * @param {Object} params - 指令参数
     * @returns {Promise<Object>} 执行结果
     */
    async runCommand(params) {
        const pla_account = db.getModel('pla_account');
        const device_status = db.getModel('device_status');
        const task_status = db.getModel('task_status');

        const { id, commandType, commandName, commandParams } = params;

        if (!id || !commandType) {
            throw new Error('账号ID和指令类型不能为空');
        }

        // 获取账号信息
        const account = await pla_account.findByPk(id);
        if (!account) {
            throw new Error('账号不存在');
        }

        // 从 device_status 检查账号是否在线
        const deviceStatus = await device_status.findByPk(account.sn_code);
        if (!deviceStatus || !deviceStatus.isOnline) {
            throw new Error('账号不在线，无法执行指令');
        }

        // 获取调度管理器并执行指令
        if (!scheduleManager.mqttClient) {
            throw new Error('MQTT客户端未初始化');
        }

        // 将驼峰格式转换为下划线格式（用于jobManager方法调用）
        const toSnakeCase = (str) => {
            // 如果已经是下划线格式，直接返回
            if (str.includes('_')) {
                return str;
            }
            // 驼峰转下划线
            return str.replace(/([A-Z])/g, '_$1').toLowerCase();
        };

        // 直接使用commandType，转换为下划线格式作为command_type
        const commandTypeSnake = toSnakeCase(commandType);
        
        // 构建基础参数
        const baseParams = {
            sn_code: account.sn_code,
            platform: account.platform_type
        };

        // 合并参数（commandParams优先）
        const finalParams = commandParams 
            ? { ...baseParams, ...commandParams } 
            : baseParams;

        // 如果有关键词相关的操作，添加关键词
        if (['search_jobs', 'get_job_list'].includes(commandTypeSnake) && account.keyword) {
            finalParams.keyword = account.keyword;
        }

        // 构建指令对象
        const command = {
            command_type: commandTypeSnake,
            command_name: commandName || commandType,
            command_params: JSON.stringify(finalParams)
        };

        // 创建任务记录
        const task = await task_status.create({
            sn_code: account.sn_code,
            taskType: commandTypeSnake,
            taskName: commandName || commandType,
            taskParams: JSON.stringify(finalParams)
        });

        // 直接执行指令
        const result = await scheduleManager.command.executeCommand(task.id, command, scheduleManager.mqttClient);

        return result;
    }

    /**
     * 获取指令详情
     * @param {Object} params - 查询参数
     * @returns {Promise<Object>} 指令详情
     */
    async getCommandDetail(params) {
        const task_commands = db.getModel('task_commands');

        const { accountId, commandId } = params;

        if (!accountId || !commandId) {
            throw new Error('账号ID和指令ID不能为空');
        }

        // 查询指令详情
        const command = await task_commands.findByPk(commandId);

        if (!command) {
            throw new Error('指令不存在');
        }

        // 解析JSON字段
        const commandDetail = command.toJSON();
        try {
            if (commandDetail.command_params) {
                commandDetail.command_params = JSON.parse(commandDetail.command_params);
            }
            if (commandDetail.result) {
                commandDetail.result = JSON.parse(commandDetail.result);
            }
        } catch (error) {
            console.warn('解析指令详情失败:', error);
        }

        return commandDetail;
    }

    /**
     * 执行账号任务（旧接口兼容）
     * @param {Object} params - 任务参数
     * @returns {Promise<Object>} 执行结果
     */
    async runTask(params) {
        const pla_account = db.getModel('pla_account');
        const device_status = db.getModel('device_status');

        const { id, taskType, taskName } = params;

        if (!id || !taskType) {
            throw new Error('账号ID和指令类型不能为空');
        }

        // 获取账号信息
        const account = await pla_account.findByPk(id);
        if (!account) {
            throw new Error('账号不存在');
        }

        // 检查账号是否启用
        if (!account.is_enabled) {
            throw new Error('账号未启用，无法执行指令');
        }

        // 从 device_status 检查账号是否在线
        const deviceStatus = await device_status.findByPk(account.sn_code);
        if (!deviceStatus || !deviceStatus.isOnline) {
            throw new Error('账号不在线，无法执行指令');
        }

        // 获取调度管理器并执行指令
        if (!scheduleManager.mqttClient) {
            throw new Error('MQTT客户端未初始化');
        }

        await scheduleManager.taskQueue.addTask(account.sn_code, {
            taskType: taskType,
            taskName: `手动任务 - ${taskName}`,
            taskParams: {
                keyword: account.keyword,
                platform: account.platform_type
            }
        });

        return {
            message: '任务已添加到队列',
            taskId: task.id
        };

       
    
    }

    /**
     * 停止账号的所有任务
     * @param {Object} params - 参数对象
     * @param {number} params.id - 账号ID
     * @param {string} params.sn_code - 设备SN码
     * @returns {Promise<Object>} 停止结果
     */
    async stopTasks(params) {
        const { id, sn_code } = params;

        if (!id && !sn_code) {
            throw new Error('账号ID或设备SN码不能为空');
        }

        const pla_account = db.getModel('pla_account');
        const task_status = db.getModel('task_status');
        const scheduleManager = require('../middleware/schedule/index.js');

        // 获取账号信息
        let account;
        if (id) {
            account = await pla_account.findByPk(id);
        } else if (sn_code) {
            account = await pla_account.findOne({ where: { sn_code } });
        }

        if (!account) {
            throw new Error('账号不存在');
        }

        const deviceSnCode = account.sn_code;

        // 1. 从任务队列中取消该设备的所有待执行任务
        const taskQueue = scheduleManager.taskQueue;
        let cancelledCount = 0;

        if (taskQueue && typeof taskQueue.cancelDeviceTasks === 'function') {
            cancelledCount = await taskQueue.cancelDeviceTasks(deviceSnCode);
        } else {
            // 如果没有 cancelDeviceTasks 方法，手动取消
            const tasks = await task_status.findAll({
                where: {
                    sn_code: deviceSnCode,
                    status: ['pending', 'running']
                }
            });

            for (const task of tasks) {
                try {
                    if (taskQueue && typeof taskQueue.cancelTask === 'function') {
                        await taskQueue.cancelTask(task.id);
                        cancelledCount++;
                    } else {
                        // 直接更新数据库
                        await task_status.update(
                            { 
                                status: 'cancelled',
                                endTime: new Date()
                            },
                            { where: { id: task.id } }
                        );
                        cancelledCount++;
                    }
                } catch (error) {
                    console.error(`[停止任务] 取消任务 ${task.id} 失败:`, error);
                }
            }
        }

        return {
            success: true,
            message: `已停止 ${cancelledCount} 个任务`,
            cancelledCount: cancelledCount,
            sn_code: deviceSnCode
        };
    }

    /**
     * 解析地址并更新经纬度
     * @param {Object} params - 参数对象
     * @param {number} params.id - 账号ID
     * @param {string} params.address - 地址（可选，如果不提供则使用账号中的地址）
     * @returns {Promise<Object>} 解析结果
     */
    async parseLocation(params) {
        const { id, address } = params;

        if (!id) {
            throw new Error('账号ID不能为空');
        }

        const pla_account = db.getModel('pla_account');
        const account = await pla_account.findByPk(id);

        if (!account) {
            throw new Error('账号不存在');
        }

        // 如果提供了地址参数，使用参数中的地址；否则使用账号中的地址
        const addressToParse = address || account.user_address;

        if (!addressToParse || addressToParse.trim() === '') {
            throw new Error('地址不能为空，请先设置用户地址');
        }

        try {
            // 调用位置服务解析地址
            const location = await locationService.getLocationByAddress(addressToParse);

            if (!location || !location.lat || !location.lng) {
                throw new Error('地址解析失败，未获取到经纬度信息');
            }

            // 更新账号的地址和经纬度
            await account.update({
                user_address: addressToParse,
                user_longitude: String(location.lng),
                user_latitude: String(location.lat)
            });

            return {
                success: true,
                message: '地址解析成功',
                data: {
                    address: addressToParse,
                    longitude: location.lng,
                    latitude: location.lat
                }
            };
        } catch (error) {
            console.error('[账号管理] 地址解析失败:', error);
            throw new Error('地址解析失败：' + (error.message || '请检查地址是否正确'));
        }
    }

    /**
     * 批量解析地址并更新经纬度
     * @param {Array<number>} ids - 账号ID数组
     * @returns {Promise<Object>} 批量解析结果
     */
    async batchParseLocation(ids) {
        if (!ids || !Array.isArray(ids) || ids.length === 0) {
            throw new Error('账号ID列表不能为空');
        }

        const pla_account = db.getModel('pla_account');
        const op = db.getModel('op');
        const accounts = await pla_account.findAll({
            where: {
                id: { [op.in]: ids }
            }
        });

        if (accounts.length === 0) {
            throw new Error('未找到指定的账号');
        }

        const results = {
            success: 0,
            failed: 0,
            details: []
        };

        // 逐个解析地址
        for (const account of accounts) {
            try {
                if (!account.user_address || account.user_address.trim() === '') {
                    results.details.push({
                        id: account.id,
                        name: account.name,
                        success: false,
                        message: '地址为空，跳过解析'
                    });
                    results.failed++;
                    continue;
                }

                const result = await this.parseLocation({
                    id: account.id,
                    address: account.user_address
                });

                results.details.push({
                    id: account.id,
                    name: account.name,
                    success: true,
                    message: '解析成功',
                    data: result.data
                });
                results.success++;
            } catch (error) {
                results.details.push({
                    id: account.id,
                    name: account.name,
                    success: false,
                    message: error.message || '解析失败'
                });
                results.failed++;
            }
        }

        return results;
    }
}

// 导出单例
module.exports = new PlaAccountService();
